package cn.net.susan.util;

import cn.net.susan.hleper.TokenHelper;
import io.micrometer.core.instrument.util.StringUtils;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.web.filter.GenericFilterBean;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.Objects;

public class JwtTokenFilter  extends GenericFilterBean {
    /**
     * 该方法里面的逻辑是：token为空时，直接放行。
     * token不为空时，如果用户名有效且用户未登录，需要将信息存入安全的上下文，并放行（因为SecurityContext仅对当前请求对应的线程有效）
     * 若用户已经登录过则直接放行
     */
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
        String token = TokenUtil.getTokenForAuthorization(httpServletRequest);
        /**
         * 判断token是否为空，如果为空直接放行，后面再交给spring security
         */
        if(Objects.isNull(token)){
            filterChain.doFilter(httpServletRequest,servletResponse);
            return;
        }

        /**
         * token不为空的情况
         */

        //获取tokenhepler来处理token
        TokenHelper tokenHelper=SpringBeanUtil.getBean("tokenHelper");

        if(Objects.nonNull(tokenHelper)){
            String username=tokenHelper.getUsernameFromToken(token);
            /**
             *  当用户名有效且用户未登录时,获取用户的信息，创建认证令牌，设置认证详情，并存入安全的上下文
             */
            if(StringUtils.isNotBlank(username)&& SecurityContextHolder.getContext().getAuthentication()==null){
                UserDetails userDetails = tokenHelper.getUserDetailsFromUsername(username);
                UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
                authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(httpServletRequest));
                SecurityContextHolder.getContext().setAuthentication(authentication);
            }
        }
        filterChain.doFilter(httpServletRequest,servletResponse);
    }
}
